package submarine;

import javax.swing.*;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.*;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 整个游戏世界
 */
public class World extends JPanel {
    public static final int WIDTH = 641;
    public static final int HEIGHT = 479;

    public static final int RUNNING = 0;
    public static final int PAUSE = 1;
    public static final int GAME_OVER = 2;
    private int state = RUNNING;

    private Battleship ship = new Battleship();
    private SeaObject[] submarines = {};
    private Mine[] mines = {};
    private Bomb[] bombs = {};

    private int score = 0;

    /**
     * 生成潜艇对象
     */
    private SeaObject nextSubmarine(){
        Random random = new Random();
        int type = random.nextInt(20);
        if(type < 10){
            return new ObserveSubmarine();
        }else if(type < 16){
            return new TorpedoSubmarine();
        }else{
            return new MineSubmarine();
        }
    }

    private int subEnterIndex = 0;
//    private int index = 0;
    /**
     * 潜艇入场
     * （每10毫秒执行一次）
     */
    private void submarineEnterAction(){
        subEnterIndex++;
        if(subEnterIndex % 40 == 0){ // 每400毫秒执行一次
            SeaObject obj = nextSubmarine();
            submarines = Arrays.copyOf(submarines, submarines.length+1);
//            submarines[index++] = obj;
            submarines[submarines.length-1] = obj;
        }
    }

    private int mineEnterIndex = 0;
    /**
     * 水雷入场
     * （每10毫秒执行一次）
     */
    private void mineEnterAction(){
        mineEnterIndex++;
        if(mineEnterIndex % 100 == 0){ // 每1000毫秒执行一次
            for(int i=0; i<submarines.length; i++) {
                if (submarines[i] instanceof MineSubmarine) {
                    //submarine.Mine mine = ((submarine.MineSubmarine) submarines[i]).shootMine();
                    MineSubmarine ms = (MineSubmarine) submarines[i];
                    Mine mine = ms.shootMine();
                    mines = Arrays.copyOf(mines, mines.length + 1);
                    mines[mines.length - 1] = mine;
                }
            }

        }
    }

    /**
     * 海洋对象移动
     */
    private void moveAction(){
        for(int i=0; i<submarines.length; i++){
            submarines[i].move();
        }
        for(int i=0; i<mines.length; i++){
            mines[i].move();
        }
        for(int i=0; i<bombs.length; i++){
            bombs[i].move();
        }
    }

    /**
     * 删除越界的海洋对象
     */
    private void outOfBoundsAction(){
        for(int i=0; i<submarines.length; i++) {
            if (submarines[i].isOutOfBounds() || submarines[i].isDead()){
                submarines[i] = submarines[submarines.length-1];
                submarines = Arrays.copyOf(submarines, submarines.length-1);
                //i--;
            }
        }
        for(int i=0; i<mines.length; i++){
            if(mines[i].isOutOfBounds() || mines[i].isDead()){
                mines[i] = mines[mines.length-1];
                mines = Arrays.copyOf(mines, mines.length-1);
                //i--;
            }
        }
        for(int i=0; i<bombs.length; i++){
            if(bombs[i].isOutOfBounds() || bombs[i].isDead()){
                bombs[i] = bombs[bombs.length-1];
                bombs = Arrays.copyOf(bombs, bombs.length-1);
                //i--;
            }
        }
    }

    /**
     * 炸弹与潜艇的碰撞
     * （每10毫秒执行一次）
     */
    public void bombBangAction(){
        for(int i=0; i<bombs.length; i++){
            Bomb b = bombs[i];
            for(int j=0; j<submarines.length; j++){
                SeaObject s = submarines[j];
                if(b.isLive() && s.isLive() && s.isHit(b)){
                    s.goDead();
                    b.goDead();
                    if(s instanceof EnemyScore){
                        EnemyScore es = (EnemyScore) s;
                        score += es.getScore();
                    }
                    if(s instanceof EnemyLife){
                        EnemyLife el = (EnemyLife) s;
                        int num = el.getLife();
                        ship.addLife(num);
                    }
                }
            }
        }
    }

    /**
     * 水雷与战舰的碰撞
     * （每10毫秒执行一次）
     */
    private void mineBangAction() {
        for(int i=0; i<mines.length; i++){
            Mine m = mines[i];
            if(m.isLive() && ship.isLive() && ship.isHit(m)){
                m.goDead();
                ship.subtractLife();
                if(ship.getLife() == 0){
                    ship.goDead();
                }
            }
        }
    }

    /**
     * 检测游戏结束
     * （每10毫秒执行一次）
     */
    private void checkGameOverAction(){
        if(ship.getLife() <= 0){
            state = GAME_OVER;
        }
    }

    /**
     * 启动程序执行
     */
    private void action(){
        // 游戏一开始，先询问是否读取存档
        File file = new File("game.sav");
        if (file.exists()) {
            // 若存档文件存在，则询问用户是否读取存档
            int r = JOptionPane.showConfirmDialog(World.this, "是否读取存档？");
            if (r == JOptionPane.YES_OPTION) {
                try {
                    FileInputStream fis = new FileInputStream(file);
                    ObjectInputStream ois = new ObjectInputStream(fis);
                    GameInfo gameInfo = (GameInfo) ois.readObject();
                    ship = gameInfo.getShip();
                    submarines = gameInfo.getSubmarines();
                    mines = gameInfo.getMines();
                    bombs = gameInfo.getBombs();
                    subEnterIndex = gameInfo.getSubEnterIndex();
                    mineEnterIndex = gameInfo.getMineEnterIndex();
                    score = gameInfo.getScore();
                    ois.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }

        // 键盘侦听器
        KeyAdapter keyAdapter = new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if(state == RUNNING) {
                    if (e.getKeyCode() == KeyEvent.VK_LEFT && ship.x > 0) {
                        ship.moveLeft();
                    }
                    if (e.getKeyCode() == KeyEvent.VK_RIGHT && ship.x + ship.width < WIDTH) {
                        ship.moveRight();
                    }
                    if (e.getKeyCode() == KeyEvent.VK_DOWN) {
                        Bomb bomb = ship.shootBomb();
                        bombs = Arrays.copyOf(bombs, bombs.length + 1);
                        bombs[bombs.length - 1] = bomb;
                    }
                }
                if(state == GAME_OVER){
                    if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                        score = 0;
                        ship = new Battleship();
                        submarines = new SeaObject[0];
                        mines = new Mine[0];
                        bombs = new Bomb[0];
                        state = RUNNING;
                    }
                }
            }
            @Override
            public void keyReleased(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_P) {
                    if(state == RUNNING){
                        state = PAUSE;
                    }else if(state == PAUSE){
                        state = RUNNING;
                    }
                }
                if (e.getKeyCode() == KeyEvent.VK_S) {
                    state = PAUSE; // 将游戏暂停
                    int r = JOptionPane.showConfirmDialog(
                            World.this, // 参数1: 确认框在游戏窗口上弹出
                            "保存游戏吗？" // 参数二: 确认框上的提示文字
                    );
                    // 判断用户点击的是"是"这个按钮才进行存档
                    if (r == JOptionPane.YES_OPTION) {
                        // 将当前World中各项信息都传入GameInfo中
                        GameInfo gameInfo = new GameInfo(ship, submarines, mines, bombs, subEnterIndex, mineEnterIndex, score);
                        try {
                            FileOutputStream fos = new FileOutputStream("game.sav");
                            ObjectOutputStream oos = new ObjectOutputStream(fos);
                            oos.writeObject(gameInfo); // 将当前游戏所有数据写入文件保存
                            oos.close();
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
                    }

                    state = RUNNING;
                }
                if(state == RUNNING) {
                    if (e.getKeyCode() == KeyEvent.VK_SPACE) {
                        Bomb bomb = ship.shootBomb();
                        bombs = Arrays.copyOf(bombs, bombs.length + 1);
                        bombs[bombs.length - 1] = bomb;
                    }
                }
            }
        };
        this.addKeyListener(keyAdapter); // 添加侦听

        Timer timer = new Timer();
        int interval = 10; // 定时间隔（以毫秒为单位）
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                if(state == RUNNING) {
                    submarineEnterAction(); // 潜艇入场
                    //for(int i=0; i<50; i++)
                    mineEnterAction();
                    moveAction();
                    bombBangAction();
                    mineBangAction();
                    outOfBoundsAction();
                    checkGameOverAction();
                    //System.out.println(submarines.length + ", " + bombs.length + ", " + mines.length);
                    repaint(); // 重画----系统自动调用paint
                }
            }
        }, interval, interval);
    }

    /**
     * 重写paint()
     * @param g:系统自带的画笔
     */
    @Override
    public void paint(Graphics g) {
        Images.sea.paintIcon(null, g, 0, 0);
        ship.paintImage(g);
        for(int i=0; i<submarines.length; i++){
            submarines[i].paintImage(g);
        }
        for(int i=0; i<mines.length; i++){
            mines[i].paintImage(g);
        }
        for(int i=0; i<bombs.length; i++){
            bombs[i].paintImage(g);
        }
        g.drawString("SCORE: " + score, 200, 50);
        g.drawString("LIFE: " + ship.getLife(), 400, 50);
        if(state == GAME_OVER){
            Images.gameover.paintIcon(null, g, 0, 0);
        }
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        World world = new World();
        world.setFocusable(true);
        frame.add(world);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(WIDTH+16, HEIGHT+39);
        frame.setTitle("潜艇大战");
        frame.setLocationRelativeTo(null);
        frame.setVisible(true); // 系统自动调用paint()

        world.action();

    }

}
